package com.ll.common.neo4j.utils;

import com.ll.common.neo4j.node.UserNode;
import com.ll.common.neo4j.relativship.InviteShip;
import org.neo4j.driver.QueryRunner;
import org.neo4j.driver.Record;
import org.neo4j.driver.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.data.neo4j.core.Neo4jTemplate;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @date 2025/9/27
 * @desc
 */
@Component
public class Neo4jUtils {

    @Autowired
    private Neo4jTemplate neo4jTemplate;

    @Autowired
    private Neo4jClient neo4jClient;

    /**
     * 根据节点id查询节点及其子节点
     * @param id 节点id
     * @return 节点及其子节点，节点及其子节点的关系以树的形式返回
     */
    public UserNode getUserNode(Integer id) {
        // 这样查询出的是该节点和该节点下的所有关系
        // Optional<UserNode> byId = neo4jTemplate.findById(id, UserNode.class);
        //  return byId.orElse(null);

        // 这是手写cql语句,查询指定节点（不包含本人)
        String cql = "match(u:User{id:$id}) return u";
        /*
         * 查询zs节点和其直接子节点
         * MATCH (u:User {name: 'zs'})-[:INVITE]->(child:User)
         * RETURN u,child;
         */
        /* 查询zs节点和zs节点的所有子节点(包括所有后代)
         * MATCH (u:User {name: 'zs'})-[:INVITE*]->(descendant:User)
         * RETURN u,descendant;
         */
        //
        Map<String, Object> map = new HashMap<>();
        map.put("id", id);
        Optional<UserNode> one = neo4jTemplate.findOne(cql, map, UserNode.class);
        return one.orElse(null);
    }

    /**
     * 添加父节点
     * @param parentNode 父节点
     */
    public void addNode(UserNode parentNode) {
        neo4jTemplate.save(parentNode);
    }


    /**
     * 添加子节点
     * @param parentNode 父节点
     * @param childNode 子节点
     */
    public void addNode(UserNode parentNode, UserNode childNode) {
        InviteShip inviteShip = new InviteShip();
        inviteShip.setTargetUserNode(childNode);
        parentNode.getInviteShips().add(inviteShip);
        neo4jTemplate.save(parentNode);
    }

    /**
     * 根据节点id查询节点及其子节点的关系
     * @param id 节点id
     * @return 节点及其子节点的关系，关系以树的形式返回
     */
    public Map<String, Object> findMapById(Integer id) {
        // COLLECT() 将数据转为列表
        // apoc.convert.toTree 是存储过程，使用call 调用，函数使用return调用
        // 针对存储过程，通过YIELD获取指定名称的执行结果
        String cql = "MATCH p = (n:User {id: $id})-[:INVITE*]->(m:User)\n" +
                "WITH COLLECT(p) AS paths\n" +
                "CALL apoc.convert.toTree(paths) YIELD value\n" +
                "RETURN value";
        Map<String, Object> map = new HashMap<>();
        map.put("id", id);

        QueryRunner queryRunner = neo4jClient.getQueryRunner();
        Result run = queryRunner.run(cql, map);
        // 结果集中只有一条记录，使用single()返回Record对象，如果有多条记录，使用list()
        Record single = run.single();
        Map<String, Object> map1 = single.get("value").asMap();
        System.out.println(map1);
        return map1;
    }
}
